<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>组件的生命周期</title>
</head>

<body>
    <!--准备好一个容器-->
    <div id="test"></div>
    <!--引入核心库-->
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <!--引入react-dom支持react操纵dom-->
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <!--引入babel用于将jsx转为js-->
    <script src="../js/babel.min.js"></script>
    <!--引入prop-types,用于对标签属性进行限制-->
    <script src="../js/prop-types.js">//引入之后全局会产生一个PropType对象</script>

    <script type="text/babel">
        //创建组件
        class Count extends React.Component {
            //设置构造器
            constructor(props) {
                console.log(`Count--constructor`)
                //有继承关系必须写super
                super(props)
                //初始化状态
                this.state = { count: 0 }//初始化状态机
            }


            //设置加1按钮的回调
            add = () => {
                //解构赋值获取原状态
                const { count } = this.state
                //在更新状态的时候操作count
                this.setState({ count: count + 1 })
            }

            //设置卸载组件按钮的回调
            death = () => {
                ReactDOM.unmountComponentAtNode(document.getElementById('test'))
            }
            //强制更新按钮的回调 
            force = () => {
                this.forceUpdate()
            }
            //组件将要挂载的钩子
            UNSAFE_componentWillMount() {
                console.log(`Count-----componentWillMount`)
            }
            //组件挂载完毕的钩子
            componentDidMount() {
                console.log(`Count-----componentDidMount`)
            }
            //设置将要卸载组件的钩子
            componentWillUnmount() {
                console.log(`Count-----componentWillUnmount`)
            }
            //控制组件更新的阀门
            shouldComponentUpdate() {//如果此方法内没有写返回值返回的是undefind 因为render会自动生成此钩子并定义返回值为true
                console.log(`Count-----shouldComponentUpdate`)
                return true //true的话阀门开启
            }
            //组件将要更新的钩子
            UNSAFE_componentWillUpdate() {
                console.log(`Count-----componentWillUpdate`)
            }
            //组件更新之后的钩子
            componentDidUpdate() {
                console.log(`Count-----componentDidUpdate`)
            }
            render() {
                console.log(`Count-----render`)
                //在这里简化状态机在标签内的书写
                const { count } = this.state
                return (
                    <div>
                        <h2>当前求和为:{count}</h2>
                        <button onClick={this.add}>喜加1</button>
                        <button onClick={this.death}>卸载组件</button>
                        <button onClick={this.force}>强制更新</button>
                    </div>
                )
            }
        }
        //父组件
        class A extends React.Component {
            //状态初始化
            state = { man: '男人' }
            changMan = () => {
                this.setState({ man: '歹人' })//更新状态
            }
            render() {
                return (
                    <div>
                        <h3>我是1</h3>
                        <button onClick={this.changMan}>换人</button>
                        <B manName={this.state.man} />
                    </div>
                )
            }
        }
        //子组件
        class B extends React.Component {
            //通过父类的render组件要接收新的props的钩子
            UNSAFE_componentWillReceiveProps(props) {//调用render之前执行
                console.log(`B----componentWillReceiveProps`, props)
            }
            //控制组件更新的阀门
            shouldComponentUpdate() {//如果此方法内没有写返回值返回的是undefind 因为render会自动生成此钩子并定义返回值为true
                console.log(`B-----shouldComponentUpdate`)
                return true //true的话阀门开启
            }
            //组件将要更新的钩子
            UNSAFE_componentWillUpdate() {
                console.log(`B-----componentWillUpdate`)
            }
            //组件更新之后的钩子
            componentDidUpdate() {
                console.log(`B-----componentDidUpdate`)
            }
            render() {
                console.log(`B-----render`)
                return (
                    <h4>我是2,我接受到的是:{this.props.manName}</h4>
                )
            }
        }
        //父组件render和子组件
        //渲染到页面 

        ReactDOM.render(<A />, document.getElementById('test'))

        /*
        总结:
        初始化阶段 由ReactDOM.render()触发初次渲染
                    1.constructor()构造器
                    2.componentWillMount()将要挂载
                    3.render()挂载
                    4.componentDidMount()挂载结束===>常用 
                                            做初始化的事例如开启定时器发送网络请求订阅消息
        更新阶段:由组件内部的this.setState()或父组件中心render触发
                    1.shouldComponentUpdate()阀门
                    2.componentWillUpdate()将要更新
                    3.render()重新挂载
                    4.componentDidUpdate()更新结束()
        卸载组件:由ReactDOM.unmountComponentAtNode()触发
                    1.componentWillUnmount()组件即将删除====>常用
                                                一般在此钩子中做收尾的事 关闭定时器 取消订阅消息


        新版本中除了卸载组件时的的willunmount 其他的带will的钩子前都需要加UNSAFE_

        getDerivedStateFromProps()"从props中得到一个派生的状态"--可以让state里的值随传入的props变化 方法内返回props


        重要的钩子
        --render:初始化或更新渲染调用
        --componentDidMount:开启监听 发送ajax请求
        --componentWillUnmount:做一些收尾工作 如清理定时器
        */
    </script>
</body>

</html>